package Injector

import (
	"github.com/shenyisyn/goft-expr/src/expr"
	"reflect"
)

var BeanFactory *BeanFactoryTmpl

type BeanFactoryTmpl struct {
	beanMapper BeanMapper
	ExprMap    map[string]interface{}
}

func NewBeanFactory() *BeanFactoryTmpl {
	return &BeanFactoryTmpl{make(BeanMapper), make(map[string]interface{})}
}

func init() {
	BeanFactory = NewBeanFactory()
}

func (t *BeanFactoryTmpl) Set(vlist ...interface{}) {
	if vlist == nil || len(vlist) == 0 {
		return
	}
	for _, v := range vlist {
		t.beanMapper.add(v)
	}
}

func (t *BeanFactoryTmpl) Get(v interface{}) interface{} {
	if v == nil {
		return nil
	}
	get_v := t.beanMapper.get(v)
	if get_v.IsValid() {
		return get_v.Interface()
	}
	return nil
}

func (t *BeanFactoryTmpl) Apply(v interface{}) {
	if v == nil {
		return
	}
	val := reflect.ValueOf(v)
	if val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	if val.Kind() != reflect.Struct {
		return
	}

	for i := 0; i < val.NumField(); i++ {
		field := val.Type().Field(i)
		if val.Field(i).CanSet() && field.Tag.Get("inject") != "" {
			if get_v := t.Get(field.Type); get_v != nil {
				val.Field(i).Set(reflect.ValueOf(get_v))
				continue
			}
			if field.Tag.Get("inject") != "-" {
				ret := expr.BeanExpr(field.Tag.Get("inject"), t.ExprMap)
				if ret != nil && !ret.IsEmpty() {
					retValue := ret[0]
					if retValue != nil {
						t.Set(retValue)
						val.Field(i).Set(reflect.ValueOf(retValue))
					}
				}
			}
		}
	}
}
